import { DataTypes, Model, Optional, Sequelize, Association } from 'sequelize';
import { sequelize } from '../config/database';
import { User } from './User';
import { CirclePost } from './CirclePost';
import { CircleCommentLike } from './CircleCommentLike';

interface CircleCommentAttributes {
    id: number;
    content: string;
    authorId: number;
    postId: number;
    parentId?: number | null;
    likeCount: number;
    createdAt?: Date;
    updatedAt?: Date;
}

interface CircleCommentCreationAttributes extends Optional<CircleCommentAttributes, 'id' | 'likeCount' | 'createdAt' | 'updatedAt'> { }

export class CircleComment extends Model<CircleCommentAttributes, CircleCommentCreationAttributes> implements CircleCommentAttributes {
    public id!: number;
    public content!: string;
    public authorId!: number;
    public postId!: number;
    public parentId?: number | null;
    public likeCount!: number;

    public readonly author?: User;
    public readonly post?: CirclePost;
    public readonly parent?: CircleComment;
    public readonly replies?: CircleComment[];
    public readonly likers?: User[];

    public static associations: {
        author: Association<CircleComment, User>;
        post: Association<CircleComment, CirclePost>;
        parent: Association<CircleComment, CircleComment>;
        replies: Association<CircleComment, CircleComment>;
        likers: Association<CircleComment, User>;
    };

    public readonly createdAt!: Date;
    public readonly updatedAt!: Date;

    public async hasLike(userId: number): Promise<boolean> {
        if (!this.likers) {
            const like = await CircleCommentLike.findOne({
                where: {
                    circleCommentId: this.id,
                    userId: userId,
                },
            });
            return !!like;
        } else {
            return this.likers.some(liker => liker.id === userId);
        }
    }

    public async addLike(userId: number): Promise<void> {
        const [like, created] = await CircleCommentLike.findOrCreate({
            where: {
                circleCommentId: this.id,
                userId: userId,
            },
        });
        if (created) {
            await this.increment('likeCount');
        }
    }

    public async removeLike(userId: number): Promise<void> {
        const deletedCount = await CircleCommentLike.destroy({
            where: {
                circleCommentId: this.id,
                userId: userId,
            },
        });
        if (deletedCount > 0) {
            await this.decrement('likeCount');
        }
    }

    public static associate(models: { User: typeof User; CirclePost: typeof CirclePost; CircleComment: typeof CircleComment; CircleCommentLike: typeof CircleCommentLike }) {
        CircleComment.belongsTo(models.User, {
            foreignKey: 'authorId',
            as: 'author',
        });

        CircleComment.belongsTo(models.CirclePost, {
            foreignKey: 'postId',
            as: 'post',
        });

        CircleComment.belongsTo(models.CircleComment, {
            foreignKey: 'parentId',
            as: 'parent',
        });

        CircleComment.hasMany(models.CircleComment, {
            foreignKey: 'parentId',
            as: 'replies',
        });

        CircleComment.belongsToMany(models.User, {
            through: models.CircleCommentLike,
            foreignKey: 'circleCommentId',
            as: 'likers',
        });
    }
}

export function initCircleComment(sequelize: Sequelize) {
    CircleComment.init({
        id: {
            type: DataTypes.INTEGER.UNSIGNED,
            autoIncrement: true,
            primaryKey: true,
        },
        content: {
            type: new DataTypes.TEXT,
            allowNull: false,
        },
        authorId: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: false,
        },
        postId: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: false,
        },
        parentId: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: true,
        },
        likeCount: {
            type: DataTypes.INTEGER.UNSIGNED,
            allowNull: false,
            defaultValue: 0,
        }
    }, {
        tableName: 'circle_comments',
        sequelize,
        timestamps: true,
    });
}

export default CircleComment; 